﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;

public class SDynamicLocator : IResourceLocator
{
    static SDynamicLocator Inst;
    /// <summary>获取材质的key是否统一了小写</summary>
    public static bool KeyIsLower = true;
    /// <summary>目录是否统一了小写</summary>
    public static bool DirectoryIsLower = true;
    /// <summary>统一的AB结尾标识符资源名字</summary>
    public static string EndExists = ".bundle";

    public static string RootPath = "http://10.40.0.209/";

    /// <summary>
    /// 初始化
    /// </summary>
    public static void Init()
    {

#if UNITY_EDITOR
            Addressables.ResourceManager.ResourceProviders.Add(new AssetDatabaseProvider());
#endif
        Addressables.ResourceManager.ResourceProviders.Add(new SAssetBundleProvider());
        Addressables.ResourceManager.ResourceProviders.Add(new BundledAssetProvider());

        RootPath = GStringBuilder.Contact(RootPath, Platform.name,"/");
      
        Inst = new SDynamicLocator();
        Addressables.AddResourceLocator(Inst);
    }

    /// <summary>添加Scene对象</summary>
    /// <param name="key"></param>
    /// <param name="depAssetPathes"></param>
    /// <param name="useEditorModel">是否使用编辑器模式</param>
    public static void AddSceneItem(string key, List<string> depAssetPathes = null,bool useEditorModel = false)
    {
        if(useEditorModel)
        {
#if UNITY_EDITOR
            string edtInterKey = GStringBuilder.Contact("Assets/",key);
            ResourceLocationBase edtLocation = new ResourceLocationBase(key, edtInterKey, typeof(AssetDatabaseProvider).FullName, typeof(SceneInstance));
            Inst.m_Locations2.Add(key, new List<IResourceLocation>(new IResourceLocation[] { edtLocation }));
            return;
#endif
        }

        string orgKey = key;
        key = GStringBuilder.Contact(key, EndExists);
        ResourceLocationBase loadLocation = new ResourceLocationBase(orgKey, orgKey, typeof(BundledAssetProvider).FullName, typeof(SceneInstance));

        if (DirectoryIsLower) key = key.ToLower();
        string loadPath = GStringBuilder.Contact(RootPath, key);

        ResourceLocationBase depLoc = new ResourceLocationBase(loadPath, loadPath, typeof(SAssetBundleProvider).FullName, typeof(IAssetBundleResource));
        loadLocation.Dependencies.Add(depLoc);

        //Debug.LogError(orgKey + "  " + loadPath);

        if (depAssetPathes != null)
        {
            int cnt = depAssetPathes.Count;
           
            for (int i = 0; i < cnt; i++)
            {
                string itemKey = depAssetPathes[i];
                if (itemKey.EndsWith(EndExists))
                    key = itemKey;
                else
                    key = GStringBuilder.Contact(itemKey, EndExists);

                string assetPath = GStringBuilder.Contact(RootPath, DirectoryIsLower ? key.ToLower() : key);

                ResourceLocationBase itemLoc = new ResourceLocationBase(itemKey, assetPath, typeof(SAssetBundleProvider).FullName, typeof(IAssetBundleResource));

                itemLoc.Data = new AssetBundleRequestOptions() {
                    BundleName = itemKey,
                    Hash = itemKey
                };

                loadLocation.Dependencies.Add(itemLoc);

                //Debug.LogError(itemKey + "  " + assetPath);
            }
        }
        //else
        //{
            //if (DirectoryIsLower) key = key.ToLower();
            //string loadPath = GStringBuilder.Contact(RootPath, key);

            //ResourceLocationBase depLoc = new ResourceLocationBase(loadPath, loadPath, typeof(SAssetBundleProvider).FullName, typeof(IAssetBundleResource));
            //loadLocation.Dependencies.Add(depLoc);
        //}

        Inst.m_Locations2.Add(orgKey, new List<IResourceLocation>(new IResourceLocation[] { loadLocation }));
    }

    /// <summary>添加GameObject对象</summary>
    /// <param name="key"></param>
    /// <param name="depAssetPathes"></param>
    public static void AddObjectItem(string key, List<string> depAssetPathes = null, bool useEditorModel = false)
    {
        AddItem(key,typeof(UnityEngine.GameObject), depAssetPathes,useEditorModel);
    }

    /// <summary>添加对象</summary>
    /// <param name="key"></param>
    /// <param name="depAssetPathes"></param>
    public static void AddItem(string key, Type abType, List<string> depAssetPathes = null, bool useEditorModel = false)
    {
        if (useEditorModel)
        {
#if UNITY_EDITOR
            string edtInterKey = GStringBuilder.Contact("Assets/", key);
           
            ResourceLocationBase edtLocation = new ResourceLocationBase(key, edtInterKey, typeof(AssetDatabaseProvider).FullName, abType);
            Inst.m_Locations2.Add(key, new List<IResourceLocation>(new IResourceLocation[] { edtLocation }));
            return;
#endif
        }

        string orgKey = key;
        key = GStringBuilder.Contact(key, EndExists);

        string assetKey = key;
        if (KeyIsLower) assetKey = assetKey.ToLower();

        ResourceLocationBase loadLocation = new ResourceLocationBase(key, assetKey, typeof(BundledAssetProvider).FullName, abType);

        if (DirectoryIsLower) key = key.ToLower();
        string loadPath = GStringBuilder.Contact(RootPath, key);

        ResourceLocationBase depLoc = new ResourceLocationBase(loadPath, loadPath, typeof(SAssetBundleProvider).FullName, typeof(IAssetBundleResource));
        loadLocation.Dependencies.Add(depLoc);

        if (depAssetPathes != null)
        {
            //depAssetPathes.Insert(0,"install_unitybuiltinshaders.bundle");
            //depAssetPathes.Insert(0, "artres/shader.bundle");

            int cnt = depAssetPathes.Count;
            IResourceLocation[] items = new IResourceLocation[cnt];

            for (int i = 0; i < cnt; i++)
            {
                string itemKey = depAssetPathes[i];
                key = GStringBuilder.Contact(itemKey, EndExists);

                string assetPath = GStringBuilder.Contact(RootPath, DirectoryIsLower ? itemKey.ToLower(): itemKey);

                //if (assetPath.IndexOf("shader") != -1) continue;

                ResourceLocationBase itemLoc = new ResourceLocationBase(itemKey, assetPath, typeof(SAssetBundleProvider).FullName, typeof(IAssetBundleResource));

                itemLoc.Data = new AssetBundleRequestOptions()
                {
                    BundleName = itemKey,
                    Hash = itemKey
                };

                loadLocation.Dependencies.Add(itemLoc);
            }
        }
        
        Inst.m_Locations2.Add(orgKey, new List<IResourceLocation>(new IResourceLocation[] { loadLocation }));
    }

    public Dictionary<string, IList<IResourceLocation>> m_Locations2 = new Dictionary<string, IList<IResourceLocation>>();
    public SDynamicLocator()
    {
       
    }

    public string LocatorId => "";
    public IEnumerable<object> Keys => null;
    public bool Locate(object key, Type type, out IList<IResourceLocation> locations)
    {
        return m_Locations2.TryGetValue((string)key, out locations);
    }
}
